package com.sy.simpleegg.base

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import org.greenrobot.eventbus.EventBus

abstract class BasePresenter<M: IModel, V: IView>: IPresenter<V>, LifecycleObserver {

    protected var mModel: M? = null
    protected var mView: V? = null

    private var mCompositeDisposable: CompositeDisposable? = null

    private val isViewAttached: Boolean
        get() = mView != null

    open fun useEventBus(): Boolean = false

    override fun attachView(mView: V) {
        this.mView = mView
        mModel = createModel()
        if (mView is LifecycleOwner){
            (mView as LifecycleOwner).lifecycle.addObserver(this)
            if (mModel != null && mModel is LifecycleOwner){
                (mView as LifecycleOwner).lifecycle.addObserver(mModel as LifecycleObserver)
            }
        }
        if (useEventBus()){
            EventBus.getDefault().register(this)
        }
    }

    override fun detechView() {
        if (useEventBus()){
            EventBus.getDefault().unregister(this)
        }
        unDispose()
        mModel?.onDetach()
        this.mView = null
        this.mModel = null
    }



    /**
     * 创建Model
     */
    open fun createModel(): M? = null

    open fun checkViewAttached(){
        if (!isViewAttached) throw ViewNotAttachedException()
    }

    open fun addDisposable(disposable: Disposable?){
        mCompositeDisposable?: CompositeDisposable()
        disposable?.let {
            mCompositeDisposable?.add(it)
        }
    }

    private fun unDispose(){
        mCompositeDisposable?.clear()
        mCompositeDisposable = null
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy(owner: LifecycleOwner){
        owner.lifecycle.removeObserver(this)
    }

    private class ViewNotAttachedException internal constructor(): RuntimeException("Please call IPresenter.attachView(IBaseView) before requesting data to the IPresenter")

}